#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>

#define offsetof(s,m) (int)(&(((s*)0)->m))

#define CLI_PATH    "/var/tmp/"      /* +5 for pid = 14 chars */
#define CLI_PERM    S_IRWXU          /* rwx for user only */

/*
 * Create a client endpoint and connect to a server.
 * Returns fd if all OK, <0 on error.
 */
int
cli_conn(const char *name)
{
    int fd, len, err, rval;
    struct sockaddr_un un;

    /* create a UNIX domain stream socket */
    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
        return(-1);

    /* fill socket address structure with our address */
    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    sprintf(un.sun_path, "%s%05d", CLI_PATH, getpid());
    len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);

    unlink(un.sun_path);        /* in case it already exists */
    if (bind(fd, (struct sockaddr *)&un, len) < 0) {
        rval = -2;
        goto errout;
    }
    if (chmod(un.sun_path, CLI_PERM) < 0) {
        rval = -3;
        goto errout;
    }

    /* fill socket address structure with server's address */
    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    strcpy(un.sun_path, name);
    len = offsetof(struct sockaddr_un, sun_path) + strlen(name);
    if (connect(fd, (struct sockaddr *)&un, len) < 0) {
        rval = -4;
        goto errout;
    }
    return fd;

errout:
    err = errno;
    close(fd);
    errno = err;
    return rval;
}

int main(int argc, char **argv)
{
    char *server_bind_file = NULL;
    int client_unix_fd;
    char buf[4096] = { 0 };
    struct iovec iov[1];
    struct msghdr msg_hdr;
    
    int recv_len = 0;

    if (argc != 3)
    {
        printf("Usage: %s server_bind_file send_msg\n", argv[0]);
        exit(0);
    }

    server_bind_file = argv[1];
    strcpy(buf, argv[2]);

    printf("server_bind_file:%s\n", server_bind_file);
    client_unix_fd =  cli_conn(server_bind_file);
    if (client_unix_fd >=0)
    {
        printf("connect to [%s] success\n",  server_bind_file);
    }

    do
    {
        //send msg
        iov[0].iov_base = buf;
        iov[0].iov_len  = strlen(buf);
        msg_hdr.msg_iov     = iov;
        msg_hdr.msg_iovlen  = 1;
        msg_hdr.msg_name    = NULL;
        msg_hdr.msg_namelen = 0;
        msg_hdr.msg_control    = NULL;
        msg_hdr.msg_controllen = 0;
        msg_hdr.msg_flags = 0;
    
        if (sendmsg(client_unix_fd, &msg_hdr, 0) == -1)
        {
            printf("sendmsg() error! errno:%d, error:%s\n", errno, strerror(errno));
            break;
        }
        else
        {
            printf("sendmsg() success\n");
        }    
    
        //recv msg
        memset(buf, 0, sizeof(buf));
        memset(&msg_hdr, 0, sizeof(msg_hdr));
    
        iov[0].iov_base = buf;
        iov[0].iov_len  = sizeof(buf);
        msg_hdr.msg_iov     = iov;
        msg_hdr.msg_iovlen  = 1;
        msg_hdr.msg_name    = NULL;
        msg_hdr.msg_namelen = 0;
        msg_hdr.msg_control    = NULL;
        msg_hdr.msg_controllen = 0;
        msg_hdr.msg_flags = 0;
    
        if ((recv_len = recvmsg(client_unix_fd, &msg_hdr, 0)) >= 0)
        {
            //假设接收到的是字符串
            printf("recvmsg:[%s][len:%d]\n", buf, recv_len);
        }
        else
        {
            printf("recvmsg() error! errno:%d, error:%s\n", errno, strerror(errno));
        }
    } while (0);

    close(client_unix_fd);

    printf("sleeping");
    while (1)
    {
        sleep(5);
        printf(".");
    }

    return 0;
}
